from django.shortcuts import render
from .common import *
from .models import *
from django.core.paginator import Paginator
from django.core import serializers
# from patient.models import Patient
from datetime import date
import detect_face
from .content import getExplain
import urllib.parse
import requests
import os
from random import sample
from string import ascii_letters, digits
import time
import json
from wechatpayv3 import WeChatPay, WeChatPayType
import logging
import uuid
from django.db.models import F
import random
import string

# 微信支付商户号（直连模式）或服务商商户号（服务商模式，即sp_mchid)
MCHID = '1663018516'

# 商户证书私钥
with open('wx_cert/apiclient_key.pem') as f:
    PRIVATE_KEY = f.read()

# 商户证书序列号
CERT_SERIAL_NO = '54A3D697434DD81DDCAC20977E6DFECC45923693'

# API v3密钥， https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
APIV3_KEY = 'langfanglangfanglangfanglangfang'

# APPID，应用ID或服务商模式下的sp_appid
APPID = 'wx79a220f839aca3bd'

# 回调地址，也可以在调用接口的时候覆盖
NOTIFY_URL = 'https://dh.bjbayes.com/langfang/api/notify'

# 微信支付平台证书缓存目录，减少证书下载调用次数，首次使用确保此目录为空目录.
# 初始调试时可不设置，调试通过后再设置，示例值:'./cert'
CERT_DIR = None

# 日志记录器，记录web请求和回调细节
logging.basicConfig(filename=os.path.join(os.getcwd(), 'demo.log'), level=logging.DEBUG, filemode='a', format='%(asctime)s - %(process)s - %(levelname)s: %(message)s')
LOGGER = logging.getLogger("demo")

# 接入模式:False=直连商户模式，True=服务商模式
PARTNER_MODE = False

# 代理设置，None或者{"https": "http://10.10.1.10:1080"}，详细格式参见https://docs.python-requests.org/zh_CN/latest/user/advanced.html
PROXY = None

# 初始化
wxpay = WeChatPay(
    wechatpay_type=WeChatPayType.NATIVE,
    mchid=MCHID,
    private_key=PRIVATE_KEY,
    cert_serial_no=CERT_SERIAL_NO,
    apiv3_key=APIV3_KEY,
    appid=APPID,
    notify_url=NOTIFY_URL,
    cert_dir=CERT_DIR,
    logger=LOGGER,
    partner_mode=PARTNER_MODE,
    proxy=PROXY)

# 商户证书私钥
# 获取项目根目录的路径
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 构建文件的绝对路径
file_path = os.path.join(base_dir, 'wx_cert/apiclient_key.pem')
with open(file_path) as f:
    PRIVATE_KEY = f.read()

# def wx_login(request):
#     try:
#         rb = json.loads(request.body.decode())
#         if not rb.get('code'):
#             return res_err('未获取code')
#         url = 'https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code'
#         response = 

appConfig = {
    "appid":"wx79a220f839aca3bd",
    "secret":"990def9227d97ce9d7cadeb2d8958cfd",
    "grant_type":"authorization_code"
}

payCnfig = {
    "mchid":"1663018516"
}

def notify(request):
    try:
        result = wxpay.callback(request.headers, request.body.decode('utf-8'))
        
        if result and result.get('event_type') == 'TRANSACTION.SUCCESS':
            resp = result.get('resource')
            appid = resp.get('appid')
            mchid = resp.get('mchid')
            out_trade_no = resp.get('out_trade_no')
            transaction_id = resp.get('transaction_id')
            trade_type = resp.get('trade_type')
            trade_state = resp.get('trade_state')
            trade_state_desc = resp.get('trade_state_desc')
            bank_type = resp.get('bank_type')
            attach = resp.get('attach')
            success_time = resp.get('success_time')
            payer = resp.get('payer')
            amount = resp.get('amount').get('total')
            # TODO: 根据返回参数进行必要的业务处理，处理完后返回200或204
            # 改变订单状态
            if trade_state == "SUCCESS":
                order = Order.objects.get(out_trade_no=out_trade_no)
                order.stat = 1
                order.trade_state = trade_state
                order.success_time = success_time
                order.save()
            else:
                order = Order.objects.get(out_trade_no=out_trade_no)
                order.trade_state = trade_state
                order.success_time = success_time
                order.save()
            return JsonResponse({'message': 'OK'}, status=200)
        else:
            return JsonResponse({'code':'FAIL','message': '失败'}, status=400)
    except:
         return JsonResponse({'code':'FAIL','message': '服务器错误'}, status=400)

def pay_miniprog(request):
    try:
        rb = json.loads(request.body.decode())
        if not rb.get('report_id'):
            return res_err('参数错误')
        ##获取用户openid
        report = Report.objects.get(id=rb.get('report_id'))
        user = User.objects.get(id=report.user_id)
        

        # 以小程序下单为例，下单成功后，将prepay_id和其他必须的参数组合传递给小程序的wx.requestPayment接口唤起支付
        # out_trade_no = ''.join(sample(ascii_letters + digits, 8))
        # 生成随机的6位数字字符串
        random_digits = ''.join(random.choices(string.digits, k=6))
        # 获取当前时间戳
        current_timestamp = int(time.time())
        # 构造订单编号，将时间戳后两位与随机数字组合
        no_prefix = ''
        if report.type == 1:
            no_prefix = 'T1-'
        else:
            no_prefix = 'J1-'
        out_trade_no = f"{no_prefix}{current_timestamp % 100:02d}{random_digits}"
        description = '报告购买'
        amount = 299
        payer = {'openid': user.openid} #oZNaz63syIAb5XG5wNGVi9lBCF60
        
        ##创建订单
        try:
            order = Order.objects.get(report_id=report.id)
            if order.stat:
                return res_err('不可重复支付')
        except Order.DoesNotExist:
            order = Order()
            order.report_id = report.id
            order.amount = amount
            order.out_trade_no = out_trade_no
            order.save()

        code, message = wxpay.pay(
            description=description,
            out_trade_no=order.out_trade_no,
            amount={'total': order.amount},
            pay_type=WeChatPayType.MINIPROG,
            payer=payer
        )
        result = json.loads(message)
        if code in range(200, 300):
            prepay_id = result.get('prepay_id')
            timestamp = str(int(time.time()))
            noncestr = str(uuid.uuid4()).replace('-', '')
            package = 'prepay_id=' + prepay_id
            sign = wxpay.sign(data=[APPID, timestamp, noncestr, package])
            signtype = 'RSA'
            res = {
                'appId': APPID,
                'timeStamp': timestamp,
                'nonceStr': noncestr,
                'package': 'prepay_id=%s' % prepay_id,
                'signType': signtype,
                'paySign': sign
            }
            return res_ok(res)
        else:
            return res_err('创建订单失败')
    except:
        return res_err('服务器错误')

def wx_login(request):
        try:
            rb = json.loads(request.body.decode())
            if not rb.get('code'):
                return res_err('获取code失败')
            #微信登录接口地址
            base_url = "https://api.weixin.qq.com/sns/jscode2session"
            appid = appConfig["appid"]  # 替换为实际的appid参数值
            secret = appConfig["secret"]  # 替换为实际的secret参数值
            js_code = rb.get('code')  # 替换为实际的js_code参数值
            grant_type = appConfig["grant_type"]

            url = f'{base_url}?appid={appid}&secret={secret}&js_code={js_code}&grant_type={grant_type}'
            response = requests.get(url)

            if response.status_code == 200:
                data = response.json()  # 解析响应的 JSON 数据
                ##判断用户是否存在
                user, created = User.objects.get_or_create(openid=data["openid"])

                if not created:
                    user.session_key = data["session_key"]
                    user.save()
                    return res_ok(user.id)
                # 在这里对获取到的数据进行处理
                user.openid = data["openid"]
                user.session_key = data["session_key"]
                user.save()
                return res_ok(user.id)
            else:
                # 处理请求失败的情况
                return  res_err('登录失败')
        except:
            return res_err('登录失败')

def report_list(request):
    rb = json.loads(request.body.decode())
    if not rb.get('user_id'):
        return res_err('用户未登录')
    r_list = ReportOrder.objects.filter(user_id=rb.get('user_id')).values('id', 'type','stat','created_at','out_trade_no').order_by('-created_at')
    data = [
        {
            "id": r['id'],
            "stat": r['stat'],
            "type": r['type'],
            "out_trade_no":r['out_trade_no'],
            "created_at":r['created_at'].strftime("%Y-%m-%d %H:%M:%S")
        }
        for r in r_list
    ]
    return res_ok(data)
def analysis_tongue(request):
    try:
        rb = json.loads(request.body.decode())
        if not rb.get('user_id'):
            return res_err('用户未登录')
        if not rb.get('imgpath'):
            return res_err('未上传图片')
        imgpath = rb.get('imgpath')
        # decoded_imgpath = urllib.parse.unquote(imgpath)
        ##开始舌象分析
        url  = f'https://machineeye.cn:3367/tongueAnalysisMiniAPP?imgpath={imgpath}'
        response = requests.get(url)
        if response.status_code == 200:
            data = response.json()  # 解析响应的 JSON 数据
            ##判断用户是否存在
            if data["code"] == '88':
                #舌象识别成功，保存报告
                db = Report()
                db.user_id = rb.get('user_id')
                db.type = 1
                db.imgpath = imgpath
                db.explain = json.dumps(data)
                db.save()
                ##创建订单
                # out_trade_no = ''.join(sample(ascii_letters + digits, 8))
                # 生成随机的6位数字字符串
                random_digits = ''.join(random.choices(string.digits, k=6))
                # 获取当前时间戳
                current_timestamp = int(time.time())
                # 构造订单编号，将时间戳后两位与随机数字组合
                out_trade_no = f"T1-{current_timestamp % 100:02d}{random_digits}"
                order = Order()
                order.report_id = db.id
                order.amount = 299
                order.out_trade_no = out_trade_no
                order.save()
                return res_ok(db.id)
            else:
                return res_err(data.message)
        else:
            # 处理请求失败的情况
            return  res_err(response.status_code)
    except:
        return res_err('识别失败')          

def analysis_job(request):
    try:
        rb = json.loads(request.body.decode())
        if not rb.get('user_id'):
            return res_err('用户未登录')
        if not rb.get('imgpath'):
            return res_err('未上传图片')
        imgpath = rb.get('imgpath')
        # decoded_imgpath = urllib.parse.unquote(imgpath)
        res = detect_face.predict(imgpath)
        if (res["code"] != 500):
            return res_err(res["message"])
        
        alg_out = res["data"]
        explain_data =  getExplain(alg_out)
        explain_data["imgpath"] = imgpath
        explain_data["crop_img"] = alg_out["crop_img"]
        explain_data["alg_out"] = alg_out

        db = Report()
        db.user_id = rb.get('user_id')
        db.type = 2
        db.alg_out = json.dumps(alg_out)
        db.imgpath = imgpath
        db.explain = json.dumps(explain_data)
        db.save()
        explain_data.update({"created_at":db.created_at.strftime("%Y-%m-%d %H:%M:%S"),"id":db.id})
        ##创建订单
        # 生成随机的6位数字字符串
        random_digits = ''.join(random.choices(string.digits, k=6))
        # 获取当前时间戳
        current_timestamp = int(time.time())
        # 构造订单编号，将时间戳后两位与随机数字组合
        out_trade_no = f"J1-{current_timestamp % 100:02d}{random_digits}"
        order = Order()
        order.report_id = db.id
        order.amount = 299
        order.out_trade_no = out_trade_no
        order.save()
        return res_ok(explain_data)
    except:
        return res_err('识别失败')

def getReport(request):
    try:
        rb = json.loads(request.body.decode())
        if not rb.get('id'):
            return res_err('缺少id')
        id = rb.get('id')
        ##查询报告的支付状态
        stat = 0
        try:
            order = Order.objects.get(report_id=id)
            stat = order.stat
        except Order.DoesNotExist:
            order = None  # 或者任何其他你想要的默认值
        
        db = Report.objects.get(id=id)
        explain_data =  json.loads(db.explain)
        explain_data["created_at"] =  db.created_at.strftime("%Y-%m-%d %H:%M:%S")
        explain_data["stat"] = stat
        explain_data["id"] = db.id
        return res_ok(explain_data)
    except :
        return res_err('获取失败')